package edu.thu.thss.rsa.yxy;

import java.math.BigInteger;

public class PublicKeyFast extends PublicKey{
//	private BigInteger[] e_additionChains;
	
	public PublicKeyFast(BigInteger n) {
		super(n);
//		ShortAdditionChains sac = new ShortAdditionChains(e);
//		e_additionChains = sac.getAdditonChains();
	}

	public BigInteger getN() {
		return n;
	}

	public void setN(BigInteger n) {
		this.n = n;
	}
	
	// RSAEncrypt: just raise m to power e (3) mod n
	public BigInteger RSAEncrypt(BigInteger m) {
//		return fastModPow(m, e_additionChains, n);
		return fastModPow(m, e, n);
//		return m.modPow(e, n);
	}

	// RSAVerify: same as encryption, since RSA is symmetric
	public BigInteger RSAVerify(BigInteger s) {
//		return fastModPow(s, e_additionChains, n);
		return fastModPow(s, e, n);
//		return s.modPow(e, n);
	}
	
//	public BigInteger fastModPow(BigInteger baseNum, BigInteger[] acs, BigInteger modNum){
//		int acsLength = acs.length;
//		int[][] biValue = new int[acsLength][2];
//		
//		for(int i = acsLength - 1; i > 0; i++){
//			for(int j = acsLength - 1; j > 0; j++){
//				if(acs[i - 1].add(acs[j-1]).compareTo(acs[i]) == 0){
//					biValue[i][0] = i - 1;
//					biValue[i][1] = j - 1;
//				}
//			}
//		}//End For
//		
//		BigInteger[] results = new BigInteger[acsLength];
//		results[0] = baseNum.mod(modNum);
//		for(int i = 1; i < acsLength; i++){
//			BigInteger a = results[biValue[i][0]];
//			BigInteger b = results[biValue[i][1]];
//			results[i] = a.multiply(b).mod(modNum); 
//		}
//		
//		return results[acsLength - 1];
//	}
	
	public static BigInteger fastModPow(BigInteger baseNum, BigInteger powNum, BigInteger modNum){
		String powString = powNum.toString(Character.MIN_RADIX); 
		BigInteger finalValue = BigInteger.ONE;

		for(int i = 0; i < powNum.bitLength(); i++){
			finalValue = finalValue.multiply(finalValue).mod(modNum);
			if(powString.charAt(i) == '1'){
				finalValue = finalValue.multiply(baseNum).mod(modNum);
			}
		}
		return finalValue;
	}
	
	public static void main(String[] args){
		BigInteger two = new BigInteger("7");
		BigInteger five = new BigInteger("560");
		BigInteger three = new BigInteger("561");
		System.out.println(fastModPow(two, five, three));
	}
}
